home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / imap-3.0 / non-ANSI / ipopd / ipop2d.c next >
Encoding:
C/C++ Source or Header  |  1993-06-10  |  11.5 KB  |  490 lines

  1. /*
  2.  * Program:    IPOP2D - IMAP2 to POP2 conversion server
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date:    28 October 1990
  13.  * Last Edited:    10 June 1993
  14.  *
  15.  * Copyright 1993 by the University of Washington
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appears in all copies and that both the
  20.  * above copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of the University of Washington not be
  22.  * used in advertising or publicity pertaining to distribution of the software
  23.  * without specific, written prior permission.  This software is made
  24.  * available "as is", and
  25.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  26.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  27.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  28.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  29.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  30.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  31.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  32.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  */
  35.  
  36.  
  37. /* Parameter files */
  38.  
  39. #include "mail.h"
  40. #include "osdep.h"
  41. #include <stdio.h>
  42. #include <ctype.h>
  43. #include <pwd.h>
  44. #include "misc.h"
  45.  
  46.  
  47. /* Size of temporary buffers */
  48. #define TMPLEN 1024
  49.  
  50.  
  51. /* Server states */
  52.  
  53. #define LISN 0
  54. #define AUTH 1
  55. #define MBOX 2
  56. #define ITEM 3
  57. #define NEXT 4
  58. #define DONE 5
  59.  
  60. /* Global storage */
  61.  
  62. char *version = "2.2(8)";    /* server version */
  63. short state = LISN;        /* server state */
  64. MAILSTREAM *stream = NIL;    /* mailbox stream */
  65. long nmsgs = 0;            /* number of messages */
  66. long current = 0;        /* current message number */
  67. long size = 0;            /* size of current message */
  68. char *user = "";        /* user name */
  69. char *pass = "";        /* password */
  70. short *msg = NIL;        /* message translation vector */
  71.  
  72.  
  73. /* Drivers we use */
  74.  
  75. extern DRIVER imapdriver,tenexdriver,mhdriver,mboxdriver,bezerkdriver;
  76.  
  77.  
  78. /* Function prototypes */
  79.  
  80. void main  ();
  81. short c_helo  ();
  82. short c_fold  ();
  83. short c_read  ();
  84. short c_retr  ();
  85. short c_acks  ();
  86. short c_ackd  ();
  87. short c_nack  ();
  88.  
  89. extern char *crypt  ();
  90.  
  91. /* Main program */
  92.  
  93. void main (argc,argv)
  94.     int argc;
  95.     char *argv[];
  96. {
  97.   char *s,*t;
  98.   char cmdbuf[TMPLEN];
  99.   mail_link (&imapdriver);    /* install the IMAP driver */
  100.   mail_link (&tenexdriver);    /* install the Tenex mail driver */
  101.   mail_link (&mhdriver);    /* install the mh mail driver */
  102.   mail_link (&mboxdriver);    /* install the mbox mail driver */
  103.   mail_link (&bezerkdriver);    /* install the Berkeley mail driver */
  104.   printf ("+ POP2 %s w/IMAP2 client (Comments to MRC@CAC.Washington.EDU)\015\012",
  105.       version);
  106.   fflush (stdout);        /* dump output buffer */
  107.   state = AUTH;            /* initial server state */
  108.                 /* command processing loop */
  109.   while ((state != DONE) && fgets (cmdbuf,TMPLEN-1,stdin)) {
  110.                 /* find end of line */
  111.     if (!strchr (cmdbuf,'\012')) {
  112.       puts ("- Command line too long\015");
  113.       state = DONE;
  114.     }
  115.     else if (!(s = strtok (cmdbuf," \015\012"))) {
  116.       puts ("- Missing or null command\015");
  117.       state = DONE;
  118.     }
  119.     else {            /* dispatch based on command */
  120.       ucase (s);        /* canonicalize case */
  121.                 /* snarf argument */
  122.       t = strtok (NIL,"\015\012");
  123.       if ((state == AUTH) && !strcmp (s,"HELO")) state = c_helo (t,argc,argv);
  124.       else if ((state == MBOX || state == ITEM) && !strcmp (s,"FOLD"))
  125.     state = c_fold (t);
  126.       else if ((state == MBOX || state == ITEM) && !strcmp (s,"READ"))
  127.     state = c_read (t);
  128.       else if ((state == ITEM) && !strcmp (s,"RETR")) state = c_retr (t);
  129.       else if ((state == NEXT) && !strcmp (s,"ACKS")) state = c_acks (t);
  130.       else if ((state == NEXT) && !strcmp (s,"ACKD")) state = c_ackd (t);
  131.       else if ((state == NEXT) && !strcmp (s,"NACK")) state = c_nack (t);
  132.       else if ((state == AUTH || state == MBOX || state == ITEM) &&
  133.            !strcmp (s,"QUIT")) {
  134.     if (t) puts ("- Bogus argument given to QUIT\015");
  135.     else {            /* valid sayonara */
  136.                 /* expunge the stream */
  137.       if (stream && nmsgs) mail_expunge (stream);
  138.       puts ("+ Sayonara\015");/* acknowledge the command */
  139.     }
  140.     state = DONE;        /* done in either case */
  141.       }
  142.       else {            /* some other or inappropriate command */
  143.     printf ("- Bogus or out of sequence command - %s\015\012",s);
  144.     state = DONE;
  145.       }
  146.     }
  147.     fflush (stdout);        /* make sure output blatted */
  148.   }
  149.   mail_close (stream);        /* clean up the stream */
  150.   exit (0);            /* all done */
  151. }
  152.  
  153. /* Parse HELO command
  154.  * Accepts: pointer to command argument
  155.  * Returns: new state
  156.  */
  157.  
  158. short c_helo (t,argc,argv)
  159.     char *t;
  160.     int argc;
  161.     char *argv[];
  162. {
  163.   char *s,*u,*p;
  164.   char tmp[TMPLEN];
  165.   struct passwd *pwd = getpwnam ("nobody");
  166.   if (!(t && *t && (u = strtok (t," ")) && (p = strtok (NIL,"\015\012")))) {
  167.     puts ("- Missing user or password\015");
  168.     return DONE;
  169.   }
  170.                 /* copy password, handle quoting */
  171.   for (s = tmp; *p; p++) *s++ = (*p == '\\') ? *++p : *p;
  172.   *s = '\0';            /* tie off string */
  173.   pass = cpystr (tmp);
  174.   if (s = strchr (u,':')) {    /* want remote mailbox? */
  175.     *s++ = '\0';        /* separate host name from user name */
  176.     user = cpystr (s);        /* note user name */
  177.     sprintf (tmp,"{%s}INBOX",u);/* initially remote INBOX */
  178.     if (pwd) {            /* try to become someone harmless */
  179.       setgid (pwd->pw_gid);    /* set group ID */
  180.       setuid (pwd->pw_uid);    /* and user ID */
  181.     }
  182.   }
  183.   else if (server_login (user = cpystr (u),pass,NIL,argc,argv))
  184.     strcpy (tmp,"INBOX");    /* local; attempt login, select INBOX */
  185.   else {
  186.     puts ("- Bad login\015");
  187.     return DONE;
  188.   }
  189.   return c_fold (tmp);        /* open default mailbox */
  190. }
  191.  
  192. /* Parse FOLD command
  193.  * Accepts: pointer to command argument
  194.  * Returns: new state
  195.  */
  196.  
  197. short c_fold (t)
  198.     char *t;
  199. {
  200.   long i,j;
  201.   char tmp[TMPLEN];
  202.   if (!(t && *t)) {        /* make sure there's an argument */
  203.     puts ("- Missing mailbox name\015");
  204.     return DONE;
  205.   }
  206.                 /* expunge old stream */
  207.   if (stream && nmsgs) mail_expunge (stream);
  208.   nmsgs = 0;            /* no more messages */
  209.   if (msg) fs_give ((void **) &msg);
  210.                 /* open mailbox, note # of messages */
  211.   if (j = (stream = mail_open (stream,t,NIL)) ? stream->nmsgs : 0) {
  212.     sprintf (tmp,"1:%d",j);    /* fetch fast information for all messages */
  213.     mail_fetchfast (stream,tmp);
  214.     msg = (short *) fs_get ((stream->nmsgs + 1) * sizeof (short));
  215.     for (i = 1; i <= j; i++)    /* find undeleted messages, add to vector */
  216.       if (!mail_elt (stream,i)->deleted) msg[++nmsgs] = i;
  217.   }
  218.   printf ("#%d messages in %s\015\012",nmsgs,stream ? stream->mailbox :
  219.       "<none>");
  220.   return MBOX;
  221. }
  222.  
  223. /* Parse READ command
  224.  * Accepts: pointer to command argument
  225.  * Returns: new state
  226.  */
  227.  
  228. short c_read (t)
  229.     char *t;
  230. {
  231.   MESSAGECACHE *elt = NIL;;
  232.                 /* set message number if possible */
  233.   if (t && *t) current = atoi (t);
  234.                 /* validity check message number */
  235.   if (current < 1 || current > nmsgs) current = 0;
  236.                 /* set size if message valid and exists */
  237.   size = msg[current] ? mail_elt (stream,msg[current])->rfc822_size : 0;
  238.                 /* display results */
  239.   printf ("=%d characters in message %d\015\012",size,current);
  240.   return ITEM;
  241. }
  242.  
  243.  
  244. /* Parse RETR command
  245.  * Accepts: pointer to command argument
  246.  * Returns: new state
  247.  */
  248.  
  249. short c_retr (t)
  250.     char *t;
  251. {
  252.   if (t) {            /* disallow argument */
  253.     puts ("- Bogus argument given to RETR\015");
  254.     return DONE;
  255.   }
  256.   if (size) {            /* message size valid? */
  257.                 /* yes, output messages */
  258.     fputs (mail_fetchheader (stream,msg[current]),stdout);
  259.     fputs (mail_fetchtext (stream,msg[current]),stdout);
  260.   }
  261.   else return DONE;        /* otherwise go away */
  262.   return NEXT;
  263. }
  264.  
  265. /* Parse ACKS command
  266.  * Accepts: pointer to command argument
  267.  * Returns: new state
  268.  */
  269.  
  270. short c_acks (t)
  271.     char *t;
  272. {
  273.   char tmp[TMPLEN];
  274.   if (t) {            /* disallow argument */
  275.     puts ("- Bogus argument given to ACKS\015");
  276.     return DONE;
  277.   }
  278.                 /* mark message as seen */
  279.   sprintf (tmp,"%d",msg[current++]);
  280.   mail_setflag (stream,tmp,"\\Seen");
  281.   return c_read (NIL);        /* end message reading transaction */
  282. }
  283.  
  284.  
  285. /* Parse ACKD command
  286.  * Accepts: pointer to command argument
  287.  * Returns: new state
  288.  */
  289.  
  290. short c_ackd (t)
  291.     char *t;
  292. {
  293.   char tmp[TMPLEN];
  294.   if (t) {            /* disallow argument */
  295.     puts ("- Bogus argument given to ACKD\015");
  296.     return DONE;
  297.   }
  298.                 /* mark message as seen and deleted */
  299.   sprintf (tmp,"%d",msg[current]);
  300.   mail_setflag (stream,tmp,"\\Seen \\Deleted");
  301.   msg[current++] = 0;        /* mark message as deleted */
  302.   return c_read (NIL);        /* end message reading transaction */
  303. }
  304.  
  305.  
  306. /* Parse NACK command
  307.  * Accepts: pointer to command argument
  308.  * Returns: new state
  309.  */
  310.  
  311. short c_nack (t)
  312.     char *t;
  313. {
  314.   if (t) {            /* disallow argument */
  315.     puts ("- Bogus argument given to NACK\015");
  316.     return DONE;
  317.   }
  318.   return c_read (NIL);        /* end message reading transaction */
  319. }
  320.  
  321. /* Co-routines from MAIL library */
  322.  
  323.  
  324. /* Message matches a search
  325.  * Accepts: IMAP2 stream
  326.  *        message number
  327.  */
  328.  
  329. void mm_searched (stream,msgno)
  330.     MAILSTREAM *stream;
  331.     long msgno;
  332. {
  333.   /* Never called */
  334. }
  335.  
  336.  
  337. /* Message exists (mailbox)
  338.     i.e. there are that many messages in the mailbox;
  339.  * Accepts: IMAP2 stream
  340.  *        message number
  341.  */
  342.  
  343. void mm_exists (stream,number)
  344.     MAILSTREAM *stream;
  345.     long number;
  346. {
  347.   /* Can't use this mechanism.  POP has no means of notifying the client of
  348.      new mail during the session. */
  349. }
  350.  
  351.  
  352. /* Message expunged
  353.  * Accepts: IMAP2 stream
  354.  *        message number
  355.  */
  356.  
  357. void mm_expunged (stream,number)
  358.     MAILSTREAM *stream;
  359.     long number;
  360. {
  361.   /* This isn't used */
  362. }
  363.  
  364.  
  365. /* Mailbox found
  366.  * Accepts: Mailbox name
  367.  */
  368.  
  369. void mm_mailbox (string)
  370.     char *string;
  371. {
  372.   /* This isn't used */
  373. }
  374.  
  375.  
  376. /* BBoard found
  377.  * Accepts: BBoard name
  378.  */
  379.  
  380. void mm_bboard (string)
  381.     char *string;
  382. {
  383.   /* This isn't used */
  384. }
  385.  
  386. /* Notification event
  387.  * Accepts: IMAP2 stream
  388.  *        string to log
  389.  *        error flag
  390.  */
  391.  
  392. void mm_notify (stream,string,errflg)
  393.     MAILSTREAM *stream;
  394.     char *string;
  395.     long errflg;
  396. {
  397.   mm_log (string,errflg);    /* just do mm_log action */
  398. }
  399.  
  400.  
  401. /* Log an event for the user to see
  402.  * Accepts: string to log
  403.  *        error flag
  404.  */
  405.  
  406. void mm_log (string,errflg)
  407.     char *string;
  408.     long errflg;
  409. {
  410.   /* Not doing anything here for now */
  411. }
  412.  
  413.  
  414. /* Log an event to debugging telemetry
  415.  * Accepts: string to log
  416.  */
  417.  
  418. void mm_dlog (string)
  419.     char *string;
  420. {
  421.   /* Not doing anything here for now */
  422. }
  423.  
  424.  
  425. /* Get user name and password for this host
  426.  * Accepts: host name
  427.  *        where to return user name
  428.  *        where to return password
  429.  *        trial count
  430.  */
  431.  
  432. void mm_login (host,username,password,trial)
  433.     char *host;
  434.     char *username;
  435.     char *password;
  436.     long trial;
  437. {
  438.   strcpy (username,user);    /* set user name */
  439.   strcpy (password,pass);    /* and password */
  440. }
  441.  
  442. /* About to enter critical code
  443.  * Accepts: stream
  444.  */
  445.  
  446. void mm_critical (stream)
  447.     MAILSTREAM *stream;
  448. {
  449.   /* Not doing anything here for now */
  450. }
  451.  
  452.  
  453. /* About to exit critical code
  454.  * Accepts: stream
  455.  */
  456.  
  457. void mm_nocritical (stream)
  458.     MAILSTREAM *stream;
  459. {
  460.   /* Not doing anything here for now */
  461. }
  462.  
  463.  
  464. /* Disk error found
  465.  * Accepts: stream
  466.  *        system error code
  467.  *        flag indicating that mailbox may be clobbered
  468.  * Returns: abort flag
  469.  */
  470.  
  471. long mm_diskerror (stream,errcode,serious)
  472.     MAILSTREAM *stream;
  473.     long errcode;
  474.     long serious;
  475. {
  476.   sleep (5);            /* can't do much better than this! */
  477.   return NIL;
  478. }
  479.  
  480.  
  481. /* Log a fatal error event
  482.  * Accepts: string to log
  483.  */
  484.  
  485. void mm_fatal (string)
  486.     char *string;
  487. {
  488.   mm_log (string,ERROR);    /* shouldn't happen normally */
  489. }
  490.